package sicnu.cs.aps.rest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sicnu.cs.aps.common.ResultInfo;
import sicnu.cs.aps.common.ResultInfoUtil;
import sicnu.cs.aps.common.annotations.OperLog;
import sicnu.cs.aps.common.enums.FileTypeEnum;
import sicnu.cs.aps.common.enums.OperEnum;
import sicnu.cs.aps.common.util.CollectionUtil;
import sicnu.cs.aps.common.util.FileCheckUtil;
import sicnu.cs.aps.common.util.RequestUtil;
import sicnu.cs.aps.domain.dto.ActivityInfoDto;
import sicnu.cs.aps.domain.dto.CollegeInfoDto;
import sicnu.cs.aps.domain.entity.*;
import sicnu.cs.aps.domain.form.*;
import sicnu.cs.aps.domain.vo.SimpleActivityVo;
import sicnu.cs.aps.service.*;
import springfox.documentation.spring.web.json.Json;

import javax.validation.constraints.NotNull;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author CaiKe
 * @date 2022/5/26 14:07
 */
@Slf4j
@RestController
@RequestMapping("/activity")
@RequiredArgsConstructor
@Api(tags = {"活动模块"})
public class ActivityResource {
    private final IActivityService activityService;
    private final IFileUploadService fileUploadService;
    private final IActivityRestrictionService activityRestrictionService;
    private final IActivityFormQuestionService activityFormQuestionService;
    private final ICollegeInfoService collegeInfoService;
    private final IStudentInfoService studentInfoService;
    private final IActivityFormService activityFormService;

    private String regex = "(,?\"[a-zA-Z]+\":\"\")";
    private Pattern pattern = Pattern.compile(regex);

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "逻辑删除活动", notes = "参数：id")
    @DeleteMapping("/deleteActivity")
    @OperLog(type = OperEnum.DELETE, description = "删除活动")
    public ResultInfo<Void> deleteActivity(@NotNull @RequestBody Integer id) {
        activityService.removeById(id);
        return ResultInfoUtil.buildSuccess();
    }

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "修改活动", notes = "参数：activity")
    @PutMapping("/updateActivity")
    @OperLog(type = OperEnum.UPDATE, description = "修改活动信息")
    public ResultInfo<Void> updateActivity(ActivityInfoForm activityInfoForm, MultipartFile file) throws IOException {
        if (!(activityInfoForm.getId() == null)) {
            return ResultInfoUtil.buildError("活动id未知");
        }
//        判断时间是否合规
        String errorInfo = activityInfoForm.isTimeLegal();
        if (!(errorInfo == null)) {
            return ResultInfoUtil.buildError(errorInfo);
        }
        // 是否修改附件
        if (!file.isEmpty()) {
            // 判断文件格式
            if (!FileCheckUtil.checkType(file)) {
                return ResultInfoUtil.buildError("文件格式不正确");
            }
            // 判断文件大小
            if (FileCheckUtil.checkSize(file)) {
                return ResultInfoUtil.buildError("文件大小不得超过10M");
            }

            // 上传新附件
            activityInfoForm.setUri(fileUploadService.uploadFile((FileInputStream) file.getInputStream(), FileTypeEnum.ATTACHMENT, file.getOriginalFilename()));

            // 删除原附件
            fileUploadService.deleteFile(activityService.getById(activityInfoForm.getId()).getUri());
        }
        Activity activity = activityInfoForm
                .withActivityStartTime(activityInfoForm.getActivityTime().get(0))
                .withActivityEndTime(activityInfoForm.getActivityTime().get(1))
                .withSignStartTime(activityInfoForm.getApplyTime().get(0))
                .withSignEndTime(activityInfoForm.getApplyTime().get(1));
        if (activityService.updateById(activity)) {
            return ResultInfoUtil.buildError("修改活动成功");
        }
        return ResultInfoUtil.buildSuccess();

    }

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "查询活动详细信息", notes = "参数：id")
    @GetMapping("/getActivityById")
    public ResultInfo<Activity> getActivity(@NotNull @Param("id") Integer id) {
        Activity activity = activityService.getById(id);
        return ResultInfoUtil.buildSuccess(activity);
    }


    @ApiOperation(value = "查询可报名活动列表")
    @GetMapping("/getActivityList")
    public ResultInfo<PageInfo<Activity>> getActivityList(ActivityQueryForm activityQueryForm) {
        StudentInfo studentInfo = studentInfoService.getById(RequestUtil.getCurrentUserId());
        Long collegeId = null;
        if (studentInfo != null) {
            collegeId = studentInfo.getCollegeId();
        }
        PageInfo<Activity> activityList = activityService.getActivityList(activityQueryForm, collegeId);
        return ResultInfoUtil.buildSuccess(activityList);
    }

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "获取学院及专业信息")
    @GetMapping("/getCollegeAndMajorInfo")
    public ResultInfo<List<CollegeInfoDto>> getCollegeAndMajorInfo() {
        return ResultInfoUtil.buildSuccess(collegeInfoService.getCollegeAndMajorInfoList());
    }

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "创建完整活动")
    @PostMapping("/createCompleteActivity")
    public ResultInfo<Void> createCompleteActivity(ActivityCreateForm activityCreateForm, MultipartFile file) {
        Gson gson = new Gson();
        // JSON转为问卷数组
        ArrayList<ActivityFormQuestionForm> questionFormList = gson.fromJson(activityCreateForm.getQuestions(), new TypeToken<ArrayList<ActivityFormQuestionForm>>() {
        }.getType());
        // 接收限制表JSON数据
        Matcher matcher = pattern.matcher(activityCreateForm.getActivityRestriction());
        String res = matcher.replaceAll("");
        ActivityRestrictionForm restrictionForm = gson.fromJson(res, ActivityRestrictionForm.class);
        // 将学院和专业数据分类装入限制表单
        List<Integer> collegeList = restrictionForm.getCollege();
        List<Long> collegeIdList = new ArrayList<>();
        List<Long> majorIdList = new ArrayList<>();
        for (Integer integer : collegeList) {
            if ((stringSize(integer) <= 4)) {
                collegeIdList.add(integer.longValue());
            } else {
                majorIdList.add(integer.longValue());
            }
        }
        restrictionForm.setCollegeIdList(collegeIdList);
        restrictionForm.setMajorIdList(majorIdList);

        // 获取活动信息
        Activity activity = Activity.builder()
                .title(activityCreateForm.getTitle())
                .content(activityCreateForm.getContent())
                .activityStartTime(activityCreateForm.getActivityTime().get(0))
                .activityEndTime(activityCreateForm.getActivityTime().get(1))
                .userId(RequestUtil.getCurrentUserId())
                .signStartTime(activityCreateForm.getApplyTime().get(0))
                .signEndTime(activityCreateForm.getApplyTime().get(1))
                .cover(activityCreateForm.getCover())
                .build();
        // 判断时间是否合规
        String errorInfo = activity.isTimeLegal();
        if (errorInfo != null) {
            return ResultInfoUtil.buildError(errorInfo);
        }
        if (file != null){
            if (!file.isEmpty()) {
                // 判断文件格式
                if (!FileCheckUtil.checkType(file)) {
                    return ResultInfoUtil.buildError("文件格式不正确");
                }
                // 判断文件大小
                if (!FileCheckUtil.checkSize(file)) {
                    return ResultInfoUtil.buildError("文件大小不得超过10M");
                }
                // 上传文件
                try {
                    String uri = fileUploadService.uploadFile((FileInputStream) file.getInputStream(), FileTypeEnum.ATTACHMENT, file.getOriginalFilename());
                    activity.setUri(uri);
                } catch (IOException e) {
                    return ResultInfoUtil.buildError("文件上传失败");
                }
            }
        }
        // 创建活动
        activityService.createActivity(activity);
        Long activityId = activity.getId();
        // 创建活动问题
        createActivityQuestions(questionFormList,activityId);
        // 创建限制表单
        createActivityRestriction(restrictionForm, activityId);
        return ResultInfoUtil.buildSuccess();
    }


    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "修改活动信息")
    @PutMapping("/university/activity")
    public ResultInfo<Void> updateActivityContent(@RequestBody Activity activity) {
        activityService.updateById(activity);
        return ResultInfoUtil.buildSuccess();
    }

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "更新活动限制条件")
    @PutMapping("/updateActivityRestriction")
    public ResultInfo<Void> updateActivityRestriction(ActivityRestrictionForm restrictionForm) {
        ActivityRestriction activityRestriction = ActivityRestriction.builder()
                .sex(restrictionForm.getSex())
                .teamSize(restrictionForm.getTeamSize())
                .collegeIds(CollectionUtil.combineList(restrictionForm.getCollegeIdList()))
                .majorIds(CollectionUtil.combineList(restrictionForm.getMajorIdList()))
                .grades(CollectionUtil.combineList(restrictionForm.getGrade()))
                .activitySize(restrictionForm.getTeamSize())
                .area(CollectionUtil.combineList(restrictionForm.getArea()))
                .build();
        // 更新限制表单
        activityRestrictionService.updateById(activityRestriction);
        return ResultInfoUtil.buildSuccess();
    }

    @ApiOperation(value = "查询所有活动")
    @GetMapping("/all")
    public ResultInfo<List<SimpleActivityVo>> getAllSimpleActivity(){
        return ResultInfoUtil.buildSuccess(activityService.getAllActivity());
    }

    @PreAuthorize("hasAnyRole('ROLE_UNIVERSITY','ROLE_UNIVERSITY_SUB')")
    @ApiOperation(value = "校方查询活动统计信息列表")
    @GetMapping("/university/activities")
    public ResultInfo<PageInfo<ActivityInfoDto>> getActivityInfoList(ActivityQueryForm queryForm) {
        return ResultInfoUtil.buildSuccess(activityService.selectActivityInfoList(queryForm));
    }


    /**
     * 创建活动
     *
     * @param activity 活动类
     * @param file     MultipartFile类
     * @return
     */
    private ResultInfo<Void> createActivity(Activity activity, MultipartFile file) {

//        判断时间是否合规
        String errorInfo = activity.isTimeLegal();
        if (errorInfo != null) {
            return ResultInfoUtil.buildError(errorInfo);
        }
        if (file != null) {
            if (!file.isEmpty()) {
                // 判断文件格式
                if (!FileCheckUtil.checkType(file)) {
                    return ResultInfoUtil.buildError("文件格式不正确");
                }
                // 判断文件大小
                if (FileCheckUtil.checkSize(file)) {
                    return ResultInfoUtil.buildError("文件大小不得超过10M");
                }
                // 上传文件
                try {
                    String uri = fileUploadService.uploadFile((FileInputStream) file.getInputStream(), FileTypeEnum.ATTACHMENT, file.getOriginalFilename());
                    activity.setUri(uri);
                } catch (IOException e) {
                    return ResultInfoUtil.buildError("文件上传失败");
                }
            }
        }
        activityService.createActivity(activity);
        return ResultInfoUtil.buildSuccess();
    }


    /**
     * 创建活动问题
     * @param questionFormList 问题列表
     * @return
     */
    @Async
    ResultInfo<Void> createActivityQuestions(List<ActivityFormQuestionForm> questionFormList, Long activityId) {
        List<ActivityFormQuestion> activityFormQuestions = new ArrayList<>();
        for (ActivityFormQuestionForm questionForm : questionFormList) {
            activityFormQuestions.add(ActivityFormQuestion.builder()
                    .question(questionForm.getQuestionName())
                    .type(questionForm.getType())
                    .options(CollectionUtil.combineList(questionForm.getAnswers()))
                    .tip(questionForm.getHint())
                    .build());
        }
        activityFormQuestionService.saveBatch(activityFormQuestions);
        // 将问题id去除并处理
        String questions = CollectionUtil.combineList(activityFormQuestions.stream().map(ActivityFormQuestion::getId).collect(Collectors.toList()));
        ActivityForm activityForm = new ActivityForm(activityId,questions);
        activityFormService.save(activityForm);
        return ResultInfoUtil.buildSuccess();
    }


    /**
     * 创建活动限制
     *
     * @param restrictionForm 限制表
     * @return
     */
    @Async
    ResultInfo<Void> createActivityRestriction(ActivityRestrictionForm restrictionForm, Long activityId) {
        ActivityRestriction activityRestriction = ActivityRestriction.builder()
                .sex(restrictionForm.getSex())
                .teamSize(restrictionForm.getTeamSize())
                .collegeIds(CollectionUtil.combineList(restrictionForm.getCollegeIdList()))
                .majorIds(CollectionUtil.combineList(restrictionForm.getMajorIdList()))
                .grades(CollectionUtil.combineList(restrictionForm.getGrade()))
                .activitySize(restrictionForm.getTeamSize())
                .area(CollectionUtil.combineList(restrictionForm.getArea()))
                .build();
        activityRestriction.setId(activityId);
        activityRestrictionService.save(activityRestriction);
        activityRestrictionService.addActivityCollegeRestriction(activityId, restrictionForm.getCollegeIdList());
        return ResultInfoUtil.buildSuccess();
    }

    final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
            99999999, 999999999, Integer.MAX_VALUE};

    /**
     * 判断位数
     * @param x
     * @return
     */
    static int stringSize(int x) {
        for (int i = 0; ; i++) {
            if (x <= sizeTable[i]) {
                return i +1;
            }
        }
    }

}